+Wed Mar 28 19:20:43 2001 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/testtext.c (create_buffer): Add missing NULL on
+ valist.
+
+ * gtk/gtkcheckmenuitem.c (gtk_check_menu_item_class_init): Fix
+ c-n-p problem with INCONSISTENT property.
+
+ [ Patch from Havoc Pennington <hp@redhat.com> ]
+
+ * gtk/gtkentry.h (struct _GtkEntryClass): add same populate_popup
+ hook.
+
+ * gtk/gtktextview.h (struct _GtkTextViewClass): add populate_popup
+ signal as a hook for extending the default popup menu
+
+ * gtk/gtkimmulticontext.c (gtk_im_multicontext_append_menuitems):
+ use radio menu items for the input method menuitems
+
+ * gtk/gtkimcontextsimple.c (check_hex): do better validation of
+ inserted unicode from Ctrl-Shift-hex input method
+
+ * gtk/gtktextbtree.c (_gtk_text_btree_insert): remove utf8
+ validatation here, already done at GtkTextBuffer level.
+
+ * gtk/gtkwidget.c (gtk_widget_class_init): add binding set, add
+ popup_menu run action signal and Shift+F10 and Menu keybindings.
+
+ * gtk/gtkentry.c: implement a default handler for popup_menu
+
+ * gtk/gtktextview.c: implement a default handler for popup_menu
+
+ * gtk/gtkmenu.c (gtk_menu_popup): select first item if popup is
+ from a key event
+
+ * gtk/gtklabel.c: remove "trailer" cruft
+
Wed Mar 28 17:27:12 2001 Jonathan Blandford <jrb@redhat.com>
* gtk/gtkrbtree.c (_gtk_rbtree_reorder): new function to
+Wed Mar 28 19:20:43 2001 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/testtext.c (create_buffer): Add missing NULL on
+ valist.
+
+ * gtk/gtkcheckmenuitem.c (gtk_check_menu_item_class_init): Fix
+ c-n-p problem with INCONSISTENT property.
+
+ [ Patch from Havoc Pennington <hp@redhat.com> ]
+
+ * gtk/gtkentry.h (struct _GtkEntryClass): add same populate_popup
+ hook.
+
+ * gtk/gtktextview.h (struct _GtkTextViewClass): add populate_popup
+ signal as a hook for extending the default popup menu
+
+ * gtk/gtkimmulticontext.c (gtk_im_multicontext_append_menuitems):
+ use radio menu items for the input method menuitems
+
+ * gtk/gtkimcontextsimple.c (check_hex): do better validation of
+ inserted unicode from Ctrl-Shift-hex input method
+
+ * gtk/gtktextbtree.c (_gtk_text_btree_insert): remove utf8
+ validatation here, already done at GtkTextBuffer level.
+
+ * gtk/gtkwidget.c (gtk_widget_class_init): add binding set, add
+ popup_menu run action signal and Shift+F10 and Menu keybindings.
+
+ * gtk/gtkentry.c: implement a default handler for popup_menu
+
+ * gtk/gtktextview.c: implement a default handler for popup_menu
+
+ * gtk/gtkmenu.c (gtk_menu_popup): select first item if popup is
+ from a key event
+
+ * gtk/gtklabel.c: remove "trailer" cruft
+
Wed Mar 28 17:27:12 2001 Jonathan Blandford <jrb@redhat.com>
* gtk/gtkrbtree.c (_gtk_rbtree_reorder): new function to
+Wed Mar 28 19:20:43 2001 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/testtext.c (create_buffer): Add missing NULL on
+ valist.
+
+ * gtk/gtkcheckmenuitem.c (gtk_check_menu_item_class_init): Fix
+ c-n-p problem with INCONSISTENT property.
+
+ [ Patch from Havoc Pennington <hp@redhat.com> ]
+
+ * gtk/gtkentry.h (struct _GtkEntryClass): add same populate_popup
+ hook.
+
+ * gtk/gtktextview.h (struct _GtkTextViewClass): add populate_popup
+ signal as a hook for extending the default popup menu
+
+ * gtk/gtkimmulticontext.c (gtk_im_multicontext_append_menuitems):
+ use radio menu items for the input method menuitems
+
+ * gtk/gtkimcontextsimple.c (check_hex): do better validation of
+ inserted unicode from Ctrl-Shift-hex input method
+
+ * gtk/gtktextbtree.c (_gtk_text_btree_insert): remove utf8
+ validatation here, already done at GtkTextBuffer level.
+
+ * gtk/gtkwidget.c (gtk_widget_class_init): add binding set, add
+ popup_menu run action signal and Shift+F10 and Menu keybindings.
+
+ * gtk/gtkentry.c: implement a default handler for popup_menu
+
+ * gtk/gtktextview.c: implement a default handler for popup_menu
+
+ * gtk/gtkmenu.c (gtk_menu_popup): select first item if popup is
+ from a key event
+
+ * gtk/gtklabel.c: remove "trailer" cruft
+
Wed Mar 28 17:27:12 2001 Jonathan Blandford <jrb@redhat.com>
* gtk/gtkrbtree.c (_gtk_rbtree_reorder): new function to
+Wed Mar 28 19:20:43 2001 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/testtext.c (create_buffer): Add missing NULL on
+ valist.
+
+ * gtk/gtkcheckmenuitem.c (gtk_check_menu_item_class_init): Fix
+ c-n-p problem with INCONSISTENT property.
+
+ [ Patch from Havoc Pennington <hp@redhat.com> ]
+
+ * gtk/gtkentry.h (struct _GtkEntryClass): add same populate_popup
+ hook.
+
+ * gtk/gtktextview.h (struct _GtkTextViewClass): add populate_popup
+ signal as a hook for extending the default popup menu
+
+ * gtk/gtkimmulticontext.c (gtk_im_multicontext_append_menuitems):
+ use radio menu items for the input method menuitems
+
+ * gtk/gtkimcontextsimple.c (check_hex): do better validation of
+ inserted unicode from Ctrl-Shift-hex input method
+
+ * gtk/gtktextbtree.c (_gtk_text_btree_insert): remove utf8
+ validatation here, already done at GtkTextBuffer level.
+
+ * gtk/gtkwidget.c (gtk_widget_class_init): add binding set, add
+ popup_menu run action signal and Shift+F10 and Menu keybindings.
+
+ * gtk/gtkentry.c: implement a default handler for popup_menu
+
+ * gtk/gtktextview.c: implement a default handler for popup_menu
+
+ * gtk/gtkmenu.c (gtk_menu_popup): select first item if popup is
+ from a key event
+
+ * gtk/gtklabel.c: remove "trailer" cruft
+
Wed Mar 28 17:27:12 2001 Jonathan Blandford <jrb@redhat.com>
* gtk/gtkrbtree.c (_gtk_rbtree_reorder): new function to
+Wed Mar 28 19:20:43 2001 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/testtext.c (create_buffer): Add missing NULL on
+ valist.
+
+ * gtk/gtkcheckmenuitem.c (gtk_check_menu_item_class_init): Fix
+ c-n-p problem with INCONSISTENT property.
+
+ [ Patch from Havoc Pennington <hp@redhat.com> ]
+
+ * gtk/gtkentry.h (struct _GtkEntryClass): add same populate_popup
+ hook.
+
+ * gtk/gtktextview.h (struct _GtkTextViewClass): add populate_popup
+ signal as a hook for extending the default popup menu
+
+ * gtk/gtkimmulticontext.c (gtk_im_multicontext_append_menuitems):
+ use radio menu items for the input method menuitems
+
+ * gtk/gtkimcontextsimple.c (check_hex): do better validation of
+ inserted unicode from Ctrl-Shift-hex input method
+
+ * gtk/gtktextbtree.c (_gtk_text_btree_insert): remove utf8
+ validatation here, already done at GtkTextBuffer level.
+
+ * gtk/gtkwidget.c (gtk_widget_class_init): add binding set, add
+ popup_menu run action signal and Shift+F10 and Menu keybindings.
+
+ * gtk/gtkentry.c: implement a default handler for popup_menu
+
+ * gtk/gtktextview.c: implement a default handler for popup_menu
+
+ * gtk/gtkmenu.c (gtk_menu_popup): select first item if popup is
+ from a key event
+
+ * gtk/gtklabel.c: remove "trailer" cruft
+
Wed Mar 28 17:27:12 2001 Jonathan Blandford <jrb@redhat.com>
* gtk/gtkrbtree.c (_gtk_rbtree_reorder): new function to
+Wed Mar 28 19:20:43 2001 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/testtext.c (create_buffer): Add missing NULL on
+ valist.
+
+ * gtk/gtkcheckmenuitem.c (gtk_check_menu_item_class_init): Fix
+ c-n-p problem with INCONSISTENT property.
+
+ [ Patch from Havoc Pennington <hp@redhat.com> ]
+
+ * gtk/gtkentry.h (struct _GtkEntryClass): add same populate_popup
+ hook.
+
+ * gtk/gtktextview.h (struct _GtkTextViewClass): add populate_popup
+ signal as a hook for extending the default popup menu
+
+ * gtk/gtkimmulticontext.c (gtk_im_multicontext_append_menuitems):
+ use radio menu items for the input method menuitems
+
+ * gtk/gtkimcontextsimple.c (check_hex): do better validation of
+ inserted unicode from Ctrl-Shift-hex input method
+
+ * gtk/gtktextbtree.c (_gtk_text_btree_insert): remove utf8
+ validatation here, already done at GtkTextBuffer level.
+
+ * gtk/gtkwidget.c (gtk_widget_class_init): add binding set, add
+ popup_menu run action signal and Shift+F10 and Menu keybindings.
+
+ * gtk/gtkentry.c: implement a default handler for popup_menu
+
+ * gtk/gtktextview.c: implement a default handler for popup_menu
+
+ * gtk/gtkmenu.c (gtk_menu_popup): select first item if popup is
+ from a key event
+
+ * gtk/gtklabel.c: remove "trailer" cruft
+
Wed Mar 28 17:27:12 2001 Jonathan Blandford <jrb@redhat.com>
* gtk/gtkrbtree.c (_gtk_rbtree_reorder): new function to
+Wed Mar 28 19:20:43 2001 Owen Taylor <otaylor@redhat.com>
+
+ * gtk/testtext.c (create_buffer): Add missing NULL on
+ valist.
+
+ * gtk/gtkcheckmenuitem.c (gtk_check_menu_item_class_init): Fix
+ c-n-p problem with INCONSISTENT property.
+
+ [ Patch from Havoc Pennington <hp@redhat.com> ]
+
+ * gtk/gtkentry.h (struct _GtkEntryClass): add same populate_popup
+ hook.
+
+ * gtk/gtktextview.h (struct _GtkTextViewClass): add populate_popup
+ signal as a hook for extending the default popup menu
+
+ * gtk/gtkimmulticontext.c (gtk_im_multicontext_append_menuitems):
+ use radio menu items for the input method menuitems
+
+ * gtk/gtkimcontextsimple.c (check_hex): do better validation of
+ inserted unicode from Ctrl-Shift-hex input method
+
+ * gtk/gtktextbtree.c (_gtk_text_btree_insert): remove utf8
+ validatation here, already done at GtkTextBuffer level.
+
+ * gtk/gtkwidget.c (gtk_widget_class_init): add binding set, add
+ popup_menu run action signal and Shift+F10 and Menu keybindings.
+
+ * gtk/gtkentry.c: implement a default handler for popup_menu
+
+ * gtk/gtktextview.c: implement a default handler for popup_menu
+
+ * gtk/gtkmenu.c (gtk_menu_popup): select first item if popup is
+ from a key event
+
+ * gtk/gtklabel.c: remove "trailer" cruft
+
Wed Mar 28 17:27:12 2001 Jonathan Blandford <jrb@redhat.com>
* gtk/gtkrbtree.c (_gtk_rbtree_reorder): new function to
G_PARAM_READABLE | G_PARAM_WRITABLE));
g_object_class_install_property (G_OBJECT_CLASS (object_class),
- PROP_ACTIVE,
+ PROP_INCONSISTENT,
g_param_spec_boolean ("inconsistent",
_("Inconsistent"),
_("Whether to display an \"inconsistent\" state."),
DELETE_TEXT,
CHANGED,
ACTIVATE,
+ POPULATE_POPUP,
MOVE_CURSOR,
INSERT_AT_CURSOR,
DELETE_FROM_CURSOR,
static void gtk_entry_paste_clipboard (GtkEntry *entry);
static void gtk_entry_toggle_overwrite (GtkEntry *entry);
static void gtk_entry_real_activate (GtkEntry *entry);
+static void gtk_entry_popup_menu (GtkWidget *widget);
/* IM Context Callbacks
*/
static void gtk_entry_paste (GtkEntry *entry,
GdkAtom selection);
static void gtk_entry_update_primary_selection (GtkEntry *entry);
-static void gtk_entry_popup_menu (GtkEntry *entry,
+static void gtk_entry_do_popup (GtkEntry *entry,
GdkEventButton *event);
static gboolean gtk_entry_activate_mnemonic (GtkWidget *widget,
gboolean group_cycling);
widget_class->drag_data_get = gtk_entry_drag_data_get;
widget_class->drag_data_delete = gtk_entry_drag_data_delete;
+ widget_class->popup_menu = gtk_entry_popup_menu;
+
class->insert_text = gtk_entry_real_insert_text;
class->delete_text = gtk_entry_real_delete_text;
class->move_cursor = gtk_entry_move_cursor;
gtk_marshal_VOID__VOID,
GTK_TYPE_NONE, 0);
+ signals[POPULATE_POPUP] =
+ gtk_signal_new ("populate_popup",
+ GTK_RUN_LAST,
+ GTK_CLASS_TYPE (object_class),
+ GTK_SIGNAL_OFFSET (GtkEntryClass, populate_popup),
+ gtk_marshal_VOID__OBJECT,
+ GTK_TYPE_NONE, 1, GTK_TYPE_MENU);
+
/* Action signals */
signals[ACTIVATE] =
}
else if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
{
- gtk_entry_popup_menu (entry, event);
+ gtk_entry_do_popup (entry, event);
entry->button = 0; /* Don't wait for release, since the menu will gtk_grab_add */
return TRUE;
append_action_signal (GtkEntry *entry,
GtkWidget *menu,
const gchar *label,
- const gchar *signal)
+ const gchar *signal,
+ gboolean sensitive)
{
GtkWidget *menuitem = gtk_menu_item_new_with_label (label);
gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
GTK_SIGNAL_FUNC (activate_cb), entry);
+ gtk_widget_set_sensitive (menuitem, sensitive);
+
gtk_widget_show (menuitem);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
}
}
static void
-gtk_entry_popup_menu (GtkEntry *entry,
- GdkEventButton *event)
+popup_position_func (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gboolean *push_in,
+ gpointer user_data)
{
- if (!entry->popup_menu)
- {
- GtkWidget *menuitem;
-
- entry->popup_menu = gtk_menu_new ();
+ GtkEntry *entry;
+ GtkWidget *widget;
+ GtkRequisition req;
+
+ entry = GTK_ENTRY (user_data);
+ widget = GTK_WIDGET (entry);
+
+ g_return_if_fail (GTK_WIDGET_REALIZED (entry));
- gtk_menu_attach_to_widget (GTK_MENU (entry->popup_menu),
- GTK_WIDGET (entry),
- popup_menu_detach);
+ gdk_window_get_origin (widget->window, x, y);
- append_action_signal (entry, entry->popup_menu, _("Cut"), "cut_clipboard");
- append_action_signal (entry, entry->popup_menu, _("Copy"), "copy_clipboard");
- append_action_signal (entry, entry->popup_menu, _("Paste"), "paste_clipboard");
+ gtk_widget_size_request (entry->popup_menu, &req);
+
+ *x += widget->allocation.width / 2;
+ *y += widget->allocation.height;
- menuitem = gtk_separator_menu_item_new ();
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (entry->popup_menu), menuitem);
+ *x = CLAMP (*x, 0, MAX (0, gdk_screen_width () - req.width));
+ *y = CLAMP (*y, 0, MAX (0, gdk_screen_height () - req.height));
+}
- gtk_im_multicontext_append_menuitems (GTK_IM_MULTICONTEXT (entry->im_context),
- GTK_MENU_SHELL (entry->popup_menu));
- }
+static void
+gtk_entry_do_popup (GtkEntry *entry,
+ GdkEventButton *event)
+{
- gtk_menu_popup (GTK_MENU (entry->popup_menu), NULL, NULL,
- NULL, NULL,
- event->button, event->time);
+ GtkWidget *menuitem;
+ GtkWidget *submenu;
+ gboolean have_selection;
+
+ if (entry->popup_menu)
+ gtk_widget_destroy (entry->popup_menu);
+
+ entry->popup_menu = gtk_menu_new ();
+
+ gtk_menu_attach_to_widget (GTK_MENU (entry->popup_menu),
+ GTK_WIDGET (entry),
+ popup_menu_detach);
+
+ have_selection = entry->current_pos != entry->selection_bound;
+
+ append_action_signal (entry, entry->popup_menu, _("Cut"), "cut_clipboard",
+ have_selection);
+ append_action_signal (entry, entry->popup_menu, _("Copy"), "copy_clipboard",
+ have_selection);
+ append_action_signal (entry, entry->popup_menu, _("Paste"), "paste_clipboard",
+ TRUE);
+
+ menuitem = gtk_separator_menu_item_new ();
+ gtk_widget_show (menuitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (entry->popup_menu), menuitem);
+
+ menuitem = gtk_menu_item_new_with_label (_("Input Methods"));
+ gtk_widget_show (menuitem);
+ submenu = gtk_menu_new ();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
+
+ gtk_menu_shell_append (GTK_MENU_SHELL (entry->popup_menu), menuitem);
+
+ gtk_im_multicontext_append_menuitems (GTK_IM_MULTICONTEXT (entry->im_context),
+ GTK_MENU_SHELL (submenu));
+
+ gtk_signal_emit (GTK_OBJECT (entry),
+ signals[POPULATE_POPUP],
+ entry->popup_menu);
+
+ if (event)
+ gtk_menu_popup (GTK_MENU (entry->popup_menu), NULL, NULL,
+ NULL, NULL,
+ event->button, event->time);
+ else
+ gtk_menu_popup (GTK_MENU (entry->popup_menu), NULL, NULL,
+ popup_position_func, entry,
+ 0, gtk_get_current_event_time ());
+}
+
+static void
+gtk_entry_popup_menu (GtkWidget *widget)
+{
+ gtk_entry_do_popup (GTK_ENTRY (widget), NULL);
}
static void
#include <gdk/gdk.h>
#include <gtk/gtkeditable.h>
#include <gtk/gtkimcontext.h>
+#include <gtk/gtkmenu.h>
#include <pango/pango.h>
#ifdef __cplusplus
gint start_pos,
gint end_pos);
+ /* Hook to customize right-click popup */
+ void (* populate_popup) (GtkEntry *entry,
+ GtkMenu *menu);
+
/* Action signals
*/
void (* activate) (GtkEntry *entry);
gint len;
GtkIMContextSimple *context_simple = GTK_IM_CONTEXT_SIMPLE (context);
-
+
+ g_return_if_fail (g_unichar_validate (ch));
+
len = g_unichar_to_utf8 (ch, buf);
buf[len] = '\0';
}
else
g_string_free (str, TRUE);
-
- if (n > 0xFFFF)
- return FALSE; /* too many digits */
- if (n == 0)
- return FALSE; /* don't insert nul bytes */
+ /* don't allow invalid Unicode or nul bytes */
+ if (n == 0 || !g_unichar_validate (n))
+ return FALSE;
context_simple->tentative_match = n;
context_simple->tentative_match_len = n_compose;
#include "gtksignal.h"
#include "gtkimmulticontext.h"
#include "gtkimmodule.h"
-#include "gtkmenuitem.h"
+#include "gtkradiomenuitem.h"
static void gtk_im_multicontext_class_init (GtkIMMulticontextClass *class);
static void gtk_im_multicontext_init (GtkIMMulticontext *im_multicontext);
{
const GtkIMContextInfo **contexts;
gint n_contexts, i;
+ GSList *group = NULL;
_gtk_im_module_list (&contexts, &n_contexts);
{
GtkWidget *menuitem;
- menuitem = gtk_menu_item_new_with_label (contexts[i]->context_name);
-
+ menuitem = gtk_radio_menu_item_new_with_label (group,
+ contexts[i]->context_name);
+
+ if ((global_context_id == NULL && group == NULL) ||
+ (global_context_id &&
+ strcmp (contexts[i]->context_id, global_context_id) == 0))
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
+ TRUE);
+
+ group = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menuitem));
+
gtk_object_set_data (GTK_OBJECT (menuitem), "gtk-context-id",
(char *)contexts[i]->context_id);
gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
if ((current_event->type != GDK_BUTTON_PRESS) &&
(current_event->type != GDK_ENTER_NOTIFY))
menu_shell->ignore_enter = TRUE;
- gdk_event_free (current_event);
}
if (menu->torn_off)
gtk_widget_show (GTK_WIDGET (menu));
gtk_widget_show (menu->toplevel);
+ if (current_event)
+ {
+ /* Also, if we're popping up from a key event, select the first
+ * item in the menu. Bad hack, but no better way to do it
+ * in current menu framework.
+ */
+ if (current_event->type == GDK_KEY_PRESS &&
+ GTK_MENU_SHELL (menu)->children)
+ {
+ gtk_menu_shell_select_item (GTK_MENU_SHELL (menu),
+ GTK_MENU_SHELL (menu)->children->data);
+ }
+
+ gdk_event_free (current_event);
+ }
+
+ gtk_menu_scroll_to (menu, menu->scroll_offset);
+
/* Find the last viewable ancestor, and make an X grab on it
*/
parent = GTK_WIDGET (menu);
NULL, NULL, activate_time) == 0))
{
if (gdk_keyboard_grab (xgrab_shell->window, TRUE,
- activate_time) == 0)
+ activate_time) == 0)
GTK_MENU_SHELL (xgrab_shell)->have_xgrab = TRUE;
else
gdk_pointer_ungrab (activate_time);
}
}
- gtk_menu_scroll_to (menu, menu->scroll_offset);
-
gtk_grab_add (GTK_WIDGET (menu));
}
/* Invalidate all iterators */
chars_changed (tree);
segments_changed (tree);
-
- g_assert (g_utf8_validate (text, len, NULL));
/*
* Chop the text up into lines and create a new segment for
if (len < 0)
len = strlen (text);
- g_assert (g_utf8_validate (text, len, NULL));
+ g_return_if_fail (g_utf8_validate (text, len, NULL));
if (len > 0)
{
enum
{
+ SET_SCROLL_ADJUSTMENTS,
+ POPULATE_POPUP,
MOVE_CURSOR,
SET_ANCHOR,
INSERT_AT_CURSOR,
COPY_CLIPBOARD,
PASTE_CLIPBOARD,
TOGGLE_OVERWRITE,
- SET_SCROLL_ADJUSTMENTS,
LAST_SIGNAL
};
static void gtk_text_view_set_scroll_adjustments (GtkTextView *text_view,
GtkAdjustment *hadj,
GtkAdjustment *vadj);
+static void gtk_text_view_popup_menu (GtkWidget *widget);
static void gtk_text_view_move_cursor (GtkTextView *text_view,
GtkMovementStep step,
static GtkAdjustment* get_hadjustment (GtkTextView *text_view);
static GtkAdjustment* get_vadjustment (GtkTextView *text_view);
-static void gtk_text_view_popup_menu (GtkTextView *text_view,
+static void gtk_text_view_do_popup (GtkTextView *text_view,
GdkEventButton *event);
static void gtk_text_view_queue_scroll (GtkTextView *text_view,
widget_class->drag_drop = gtk_text_view_drag_drop;
widget_class->drag_data_received = gtk_text_view_drag_data_received;
+ widget_class->popup_menu = gtk_text_view_popup_menu;
+
container_class->add = gtk_text_view_add;
container_class->remove = gtk_text_view_remove;
container_class->forall = gtk_text_view_forall;
GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
widget_class->set_scroll_adjustments_signal = signals[SET_SCROLL_ADJUSTMENTS];
+ signals[POPULATE_POPUP] =
+ gtk_signal_new ("populate_popup",
+ GTK_RUN_LAST,
+ GTK_CLASS_TYPE (object_class),
+ GTK_SIGNAL_OFFSET (GtkTextViewClass, populate_popup),
+ gtk_marshal_VOID__OBJECT,
+ GTK_TYPE_NONE, 1, GTK_TYPE_MENU);
+
/*
* Key bindings
*/
}
else if (event->button == 3)
{
- gtk_text_view_popup_menu (text_view, event);
+ gtk_text_view_do_popup (text_view, event);
}
}
else if ((event->type == GDK_2BUTTON_PRESS ||
append_action_signal (GtkTextView *text_view,
GtkWidget *menu,
const gchar *label,
- const gchar *signal)
+ const gchar *signal,
+ gboolean sensitive)
{
GtkWidget *menuitem = gtk_menu_item_new_with_label (label);
gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
GTK_SIGNAL_FUNC (activate_cb), text_view);
+ gtk_widget_set_sensitive (menuitem, sensitive);
+
gtk_widget_show (menuitem);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
}
}
static void
-gtk_text_view_popup_menu (GtkTextView *text_view,
- GdkEventButton *event)
+popup_position_func (GtkMenu *menu,
+ gint *x,
+ gint *y,
+ gboolean *push_in,
+ gpointer user_data)
{
- if (!text_view->popup_menu)
- {
- GtkWidget *menuitem;
-
- text_view->popup_menu = gtk_menu_new ();
+ GtkTextView *text_view;
+ GtkWidget *widget;
+ GdkRectangle cursor_rect;
+ GdkRectangle onscreen_rect;
+ gint root_x, root_y;
+ GtkTextIter iter;
+ GtkRequisition req;
+
+ text_view = GTK_TEXT_VIEW (user_data);
+ widget = GTK_WIDGET (text_view);
+
+ g_return_if_fail (GTK_WIDGET_REALIZED (text_view));
- gtk_menu_attach_to_widget (GTK_MENU (text_view->popup_menu),
- GTK_WIDGET (text_view),
- popup_menu_detach);
+ gdk_window_get_origin (widget->window, &root_x, &root_y);
- append_action_signal (text_view, text_view->popup_menu, _("Cut"), "cut_clipboard");
- append_action_signal (text_view, text_view->popup_menu, _("Copy"), "copy_clipboard");
- append_action_signal (text_view, text_view->popup_menu, _("Paste"), "paste_clipboard");
+ gtk_text_buffer_get_iter_at_mark (get_buffer (text_view),
+ &iter,
+ gtk_text_buffer_get_insert (get_buffer (text_view)));
- menuitem = gtk_separator_menu_item_new ();
- gtk_widget_show (menuitem);
- gtk_menu_shell_append (GTK_MENU_SHELL (text_view->popup_menu), menuitem);
+ gtk_text_view_get_iter_location (text_view,
+ &iter,
+ &cursor_rect);
- gtk_im_multicontext_append_menuitems (GTK_IM_MULTICONTEXT (text_view->im_context),
- GTK_MENU_SHELL (text_view->popup_menu));
+ gtk_text_view_get_visible_rect (text_view, &onscreen_rect);
+
+ gtk_widget_size_request (text_view->popup_menu, &req);
+
+ /* can't use rectangle_intersect since cursor rect can have 0 width */
+ if (cursor_rect.x >= onscreen_rect.x &&
+ cursor_rect.x < onscreen_rect.x + onscreen_rect.width &&
+ cursor_rect.y >= onscreen_rect.y &&
+ cursor_rect.y < onscreen_rect.y + onscreen_rect.height)
+ {
+ gtk_text_view_buffer_to_window_coords (text_view,
+ GTK_TEXT_WINDOW_WIDGET,
+ cursor_rect.x, cursor_rect.y,
+ &cursor_rect.x, &cursor_rect.y);
+
+ *x = root_x + cursor_rect.x + cursor_rect.width;
+ *y = root_y + cursor_rect.y + cursor_rect.height;
}
+ else
+ {
+ /* Just center the menu, since cursor is offscreen. */
+ *x = root_x + (widget->allocation.width / 2 - req.width / 2);
+ *y = root_y + (widget->allocation.height / 2 - req.height / 2);
+ }
+
+ /* Ensure sanity */
+ *x = CLAMP (*x, root_x, (root_x + widget->allocation.width));
+ *y = CLAMP (*y, root_y, (root_y + widget->allocation.height));
- gtk_menu_popup (GTK_MENU (text_view->popup_menu), NULL, NULL,
- NULL, NULL,
- event->button, event->time);
+ *x = CLAMP (*x, 0, MAX (0, gdk_screen_width () - req.width));
+ *y = CLAMP (*y, 0, MAX (0, gdk_screen_height () - req.height));
}
+static void
+gtk_text_view_do_popup (GtkTextView *text_view,
+ GdkEventButton *event)
+{
+ GtkWidget *menuitem;
+ GtkWidget *submenu;
+ gboolean have_selection;
+
+ if (text_view->popup_menu)
+ gtk_widget_destroy (text_view->popup_menu);
+
+ text_view->popup_menu = gtk_menu_new ();
+
+ gtk_menu_attach_to_widget (GTK_MENU (text_view->popup_menu),
+ GTK_WIDGET (text_view),
+ popup_menu_detach);
+
+ have_selection = gtk_text_buffer_get_selection_bounds (get_buffer (text_view),
+ NULL, NULL);
+
+ append_action_signal (text_view, text_view->popup_menu, _("Cut"), "cut_clipboard",
+ have_selection);
+ append_action_signal (text_view, text_view->popup_menu, _("Copy"), "copy_clipboard",
+ have_selection);
+ append_action_signal (text_view, text_view->popup_menu, _("Paste"), "paste_clipboard",
+ TRUE);
+
+ menuitem = gtk_separator_menu_item_new ();
+ gtk_widget_show (menuitem);
+ gtk_menu_shell_append (GTK_MENU_SHELL (text_view->popup_menu), menuitem);
+
+ menuitem = gtk_menu_item_new_with_label (_("Input Methods"));
+ gtk_widget_show (menuitem);
+ submenu = gtk_menu_new ();
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
+ gtk_menu_shell_append (GTK_MENU_SHELL (text_view->popup_menu), menuitem);
+
+ gtk_im_multicontext_append_menuitems (GTK_IM_MULTICONTEXT (text_view->im_context),
+ GTK_MENU_SHELL (submenu));
+
+ gtk_signal_emit (GTK_OBJECT (text_view),
+ signals[POPULATE_POPUP],
+ text_view->popup_menu);
+
+ if (event)
+ gtk_menu_popup (GTK_MENU (text_view->popup_menu), NULL, NULL,
+ NULL, NULL,
+ event->button, event->time);
+ else
+ gtk_menu_popup (GTK_MENU (text_view->popup_menu), NULL, NULL,
+ popup_position_func, text_view,
+ 0, gtk_get_current_event_time ());
+}
+static void
+gtk_text_view_popup_menu (GtkWidget *widget)
+{
+ gtk_text_view_do_popup (GTK_TEXT_VIEW (widget), NULL);
+}
/* Child GdkWindows */
#include <gtk/gtkcontainer.h>
#include <gtk/gtkimcontext.h>
#include <gtk/gtktextbuffer.h>
+#include <gtk/gtkmenu.h>
#ifdef __cplusplus
extern "C" {
{
GtkContainerClass parent_class;
+ void (* set_scroll_adjustments) (GtkTextView *text_view,
+ GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment);
+
+ void (* populate_popup) (GtkTextView *text_view,
+ GtkMenu *menu);
+
/* These are all RUN_ACTION signals for keybindings */
/* move insertion point */
void (* paste_clipboard) (GtkTextView *text_view);
/* overwrite */
void (* toggle_overwrite) (GtkTextView *text_view);
- void (* set_scroll_adjustments) (GtkTextView *text_view,
- GtkAdjustment *hadjustment,
- GtkAdjustment *vadjustment);
};
GtkType gtk_text_view_get_type (void) G_GNUC_CONST;
#include "gdk/gdk.h"
#include "gdk/gdkprivate.h" /* Used in gtk_reset_shapes_recurse to avoid copy */
#include "gobject/gvaluecollector.h"
+#include "gdk/gdkkeysyms.h"
#define WIDGET_CLASS(w) GTK_WIDGET_GET_CLASS (w)
NO_EXPOSE_EVENT,
VISIBILITY_NOTIFY_EVENT,
WINDOW_STATE_EVENT,
+ POPUP_MENU,
LAST_SIGNAL
};
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
+ GtkBindingSet *binding_set;
parent_class = gtk_type_class (GTK_TYPE_OBJECT);
gtk_marshal_BOOLEAN__BOXED,
GTK_TYPE_BOOL, 1,
GTK_TYPE_GDK_EVENT);
+ widget_signals[POPUP_MENU] =
+ gtk_signal_new ("popup_menu",
+ GTK_RUN_LAST | GTK_RUN_ACTION,
+ GTK_CLASS_TYPE (object_class),
+ GTK_SIGNAL_OFFSET (GtkWidgetClass, popup_menu),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ binding_set = gtk_binding_set_by_class (klass);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_F10, GDK_SHIFT_MASK,
+ "popup_menu", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_Menu, 0,
+ "popup_menu", 0);
}
static void
GtkSelectionData *selection_data,
guint info,
guint time);
+
+ /* Signals used only for keybindings */
+ void (* popup_menu) (GtkWidget *widget);
- /* Padding for future expandsion */
+ /* Padding for future expansion */
GtkFunction pad1;
GtkFunction pad2;
GtkFunction pad3;
{
g_signal_connect_data (G_OBJECT (tag),
"event",
- tag_event_handler,
+ G_CALLBACK (tag_event_handler),
NULL, NULL, FALSE, FALSE);
}
}
buffer->invisible_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
- "invisible", TRUE);
+ "invisible", TRUE, NULL);
buffer->not_editable_tag =
gtk_text_buffer_create_tag (buffer->buffer, NULL,
{
g_signal_connect_data (G_OBJECT (tag),
"event",
- tag_event_handler,
+ G_CALLBACK (tag_event_handler),
NULL, NULL, FALSE, FALSE);
}
}
buffer->invisible_tag = gtk_text_buffer_create_tag (buffer->buffer, NULL,
- "invisible", TRUE);
+ "invisible", TRUE, NULL);
buffer->not_editable_tag =
gtk_text_buffer_create_tag (buffer->buffer, NULL,